﻿using System;
using System.Collections.Specialized;

namespace Outfish {
	
	/// <summary>
	/// Encapsulates all info (except cookies) required to make a web request
	/// </summary>
	public class ScrapeRequest : IScrapeRequest {

		#region constructors

		/// <summary>Creates a new GET Request</summary>
		/// <param name="uri">URI to retrieve</param>
		public ScrapeRequest( Uri uri ){ 
			if( uri == null ){ throw new ArgumentNullException("uri"); }
			this.Uri = uri; 
		}

		/// <summary>Creates a new GET Request</summary>
		/// <param name="uriString"></param>
		public ScrapeRequest( string uriString ){
			if( uriString == null ){ throw new ArgumentNullException("uriString"); }
			this.UriString = uriString;
		}
		
		/// <summary>Creates a new GET or POST request</summary>
		/// <param name="uri">URI to retrieve</param>
		/// <param name="postData">null = GET, non-null = POST</param></param></param>
		public ScrapeRequest( Uri uri, NameValueCollection postData ){
			if( uri == null ){ throw new ArgumentNullException("uri"); }
			this.Uri = uri;
			this.NameValueCollectionPostData = postData;
		}
		
		/// <summary>Create a new GET or POST request</summary>
		/// <param name="uri">URI to retrieve</param>
		/// <param name="postData">null = GET, non-null = POST</param>
		public ScrapeRequest( Uri uri, IPostData postData ){
			if( uri == null ){ throw new ArgumentNullException("uri"); }
			this.Uri = uri;
			this.PostData = postData;
		}

		/// <summary>Creates a new GET or POST request</summary>
		/// <param name="uri">URI to retrieve</param>
		/// <param name="postData">null = GET, non-null = POST</param></param></param>
		public ScrapeRequest( string uriString, NameValueCollection postData ){
			if( uriString == null ){ throw new ArgumentNullException("uriString"); }
			this.UriString = uriString;
			this.NameValueCollectionPostData = postData;
		}
		
		/// <summary>Create a new GET or POST request</summary>
		/// <param name="uri">URI to retrieve</param>
		/// <param name="postData">null = GET, non-null = POST</param>
		public ScrapeRequest( string uriString, IPostData postData ){
			if( uriString == null ){ throw new ArgumentNullException("uriString"); }
			this.UriString = uriString;
			this.PostData = postData;
		}
		
		#endregion
		
		/// <summary>
		/// Gets the URI the request will go to
		/// </summary>
		public Uri Uri{ get; private set; }
		
		/// <summary>
		/// Gets the POST data that will be submitted with a POST request.
		/// </summary>
		/// <returns>null for GET requests</returns>
		public IPostData PostData{ get; private set; }
		
		/// <summary>
		/// Gets the request method (GET or POST) depending if there is POST data present.
		/// </summary>
		public string Method{ get{ return this.PostData != null ? "POST" : "GET"; } }
		
		/// <summary>
		/// Get or Sets the Referrer that is required to make this request.
		/// </summary>
		public string Referrer{ get; set; }

		/// <summary>Enables(the default) or diables redirection for this request.</summary>
		public bool IgnoreRedirection{ get; set; }

		/// <summary>The specific timeout in milliseconds to use for this request.  Overrides timeout in scraper.</summary>
		public int? Timeout{ get; set; }

		public override string ToString() {

			if( this.PostData == null ){
				return "GET " + this.Uri.ToString();
			} else {
				return "POST " + this.Uri.ToString() 
					+ "\r\nPostData  --> "
					+ this.PostData.ToString();
			}
		}

		/// <summary>
		/// Converts NameValueCollection to query string that can be appended to a base url.
		/// </summary>
		/// <remarks>
		/// Convenience short cut to FormUrlPostData.GetQueryString(...)
		/// </remarks>
		/// <param name="queryParameters">parameters to construct into a string</param>
		/// <returns>query string (without the leading '?')</returns>
		static public string ToQuery( NameValueCollection queryParameters ){
			return FormUrlPostData.GetQueryString( queryParameters );
		}

		#region private methods
		
		/// <summary>
		/// constructor helper - validates the string and converts it to Uri, 
		/// </summary>
		string UriString { 
			set{ 
				try{
					this.Uri = new Uri( value ); 
				}
				catch(System.UriFormatException ex){
					throw new ArgumentException("Invalid URI: " + value, ex);
				}
			}
		}

		/// <summary>
		/// Construction helper - converts NameValueCollection to IPostData
		/// </summary>
		NameValueCollection NameValueCollectionPostData{
			set{ 
				if( value != null ){
					this.PostData = new FormUrlPostData( value );
				}
			}
		}

		#endregion
		
		
	}

	
}
